package edu.unika.aifb.graphindex;

import java.io.File;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

import joptsimple.OptionParser;
import joptsimple.OptionSet;

import org.apache.log4j.Logger;

import edu.unika.aifb.graphindex.importer.Importer;
import edu.unika.aifb.graphindex.importer.ImporterRegistry;
import edu.unika.aifb.graphindex.importer.db.ConnectionPool;
import edu.unika.aifb.graphindex.importer.db.DBImporter;
import edu.unika.aifb.graphindex.importer.db.metadata.Database;
import edu.unika.aifb.graphindex.importer.db.metadata.DatabaseFactory;
import edu.unika.aifb.graphindex.index.IndexConfiguration;
import edu.unika.aifb.graphindex.index.IndexCreator;
import edu.unika.aifb.graphindex.index.IndexDirectory;

public class Main {
	
	private static final Logger log = Logger.getLogger(Main.class);
	
	//program arguments: -o C:\rane\workspace3.6.1\DBGraphIndex\indexes\dbindex -kw -sd -triples -jdbcUrl jdbc:derby://localhost:1527/.. -dbUser STATISTIK -dbPassword STATISTIK -dbSchema=STATISTIK -ip db
	//vm arguments: -Xms1024m -Xmx1024m
	
	public static void main(String[] args) throws Exception {
		OptionParser op = new OptionParser();
		op.accepts("o", "output directory")
			.withRequiredArg().ofType(String.class).describedAs("directory");
		op.accepts("jdbcUrl", "connection string to import from database - jdbc:derby://localhost:1527/..").withRequiredArg().ofType(String.class).describedAs("jdbc connection string");
		op.accepts("dbUser", "database user").withRequiredArg().ofType(String.class).describedAs("database user");
		op.accepts("dbPassword", "database password").withRequiredArg().ofType(String.class).describedAs("database password");
		op.accepts("dbSchema", "database schema to import").withRequiredArg().ofType(String.class).describedAs("database schema");
		
		op.accepts("sk", "structure index path length")
			.withRequiredArg().ofType(Integer.class).describedAs("structure index path length, default: 1");
		op.accepts("nk", "neighborhood size")
			.withRequiredArg().ofType(Integer.class).describedAs("neighborhood size, default: 1");
		op.accepts("kw", "keyword index");
		op.accepts("sd", "data extensions");
		op.accepts("resume", "resume from analyzse, structure or keyword").withRequiredArg().ofType(String.class);
		op.accepts("triples", "triples only");
		op.accepts("bwonly", "backward only");
		op.accepts("fwonly", "forward only");
		op.accepts("dt", "include datatypes");
		op.accepts("re", "eliminate reflexive edges");
		op.accepts("idx", "create a single index").withRequiredArg().ofType(String.class);
		op.accepts("ip", "importer to use").withRequiredArg().ofType(String.class);
		
		OptionSet os = op.parse(args);
		
		if (!os.has("o") || !os.has("jdbcUrl")){
			op.printHelpOn(System.out);
			return;
		}

		String directory = (String)os.valueOf("o");
		int sk = os.has("sk") ? (Integer)os.valueOf("sk") : 1;
		int nk = os.has("nk") ? (Integer)os.valueOf("nk") : 1;
		boolean triplesOnly = os.has("triples");
		boolean backwardOnly = os.has("bwonly");
		boolean forwardOnly = os.has("fwonly");
		boolean eliminateRE = os.has("re");
		String singleIndex = os.has("idx") ? (String)os.valueOf("idx") : null;
		String importerType = os.has("ip") ? (String)os.valueOf("ip") : null;
		String jdbcUrl = os.has("jdbcUrl") ? (String)os.valueOf("jdbcUrl") : null;
		String dbUser = os.has("dbUser") ? (String)os.valueOf("dbUser") : "";
		String dbPassword = os.has("dbPassword") ? (String)os.valueOf("dbPassword") : "";
		String dbSchema = os.has("dbSchema") ? (String)os.valueOf("dbSchema") : null;
		
		if (backwardOnly && forwardOnly) {
			log.error("only one of bwonly and fwonly can be specified");
			return;
		}
			
		
		int startFrom = IndexCreator.STEP_DATA;
		if (os.has("resume")) {
			String from = (String)os.valueOf("resume");
			if (from.equals("a"))
				startFrom = IndexCreator.STEP_ANALYZE;
			if (from.equals("s"))
				startFrom = IndexCreator.STEP_STRUCTURE;
			if (from.equals("p"))
				startFrom = IndexCreator.STEP_PARTITION;
			if (from.equals("w"))
				startFrom = IndexCreator.STEP_KEYWORD_PREPARE;
			if (from.equals("k"))
				startFrom = IndexCreator.STEP_KEYWORD;
			if (from.equals("e"))
				startFrom = IndexCreator.STEP_KEYWORD_RESUME;
			if (from.equals("db"))
				startFrom = IndexCreator.STEP_DB_INDEX;
		}
		
		List<String> files = os.nonOptionArguments();
		
		if (files.size() == 1) {
			File f = new File(files.get(0));
			if (f.isDirectory()) {
				files = new ArrayList<String>();	
				for (File file : f.listFiles())
					if (!file.getName().startsWith("."))
						files.add(file.getAbsolutePath());
			}
		}
		
		ConnectionPool connectionPool = new ConnectionPool();
		Connection connection = connectionPool.createConnection(jdbcUrl, dbUser, dbPassword, null);
		
		Database database = DatabaseFactory.createDatabase(connection, dbSchema);
		database.print();
		
		Importer importer = ImporterRegistry.getInstance().getImporter(importerType);
		((DBImporter)importer).setConnectionPool(connectionPool);
		((DBImporter)importer).setDatabase(database);
		
		IndexCreator ic = new IndexCreator(new IndexDirectory(directory));
		importer.setIgnoreDataTypes(!os.has("dt"));
		ic.setImporter(importer);
		ic.setCreateDataIndex(true);
		ic.setCreateStructureIndex(sk > 0);
		ic.setCreateKeywordIndex(os.has("kw"));
		ic.setKWNeighborhoodSize(nk);
		ic.setSIPathLength(sk);
		ic.setStructureBasedDataPartitioning(os.has("sd"));
		ic.setSICreateDataExtensions(os.has("sd"));
		ic.setOption(IndexConfiguration.TRIPLES_ONLY, triplesOnly);
		ic.setOption(IndexConfiguration.SP_BACKWARD_ONLY, backwardOnly);
		ic.setOption(IndexConfiguration.SP_FORWARD_ONLY, forwardOnly);
		ic.setOption(IndexConfiguration.SP_ELIMINATE_REFLEXIVE_EDGES, eliminateRE);
		
		if (singleIndex == null)
			ic.create(startFrom);
		else
			ic.createSingleIndex(singleIndex);
	}

}
